package com.lineage.server.model.shop;

import com.lineage.config.ConfigRate;
import com.lineage.server.datatables.ItemTable;
import com.lineage.server.datatables.lock.CastleReading;
import com.lineage.server.datatables.lock.TownReading;
import com.lineage.server.model.Instance.L1ItemInstance;
import com.lineage.server.model.Instance.L1PcInstance;
import com.lineage.server.model.L1CastleLocation;
import com.lineage.server.model.L1PcInventory;
import com.lineage.server.model.L1TaxCalculator;
import com.lineage.server.model.L1TownLocation;
import com.lineage.server.serverpackets.S_Disconnect;
import com.lineage.server.serverpackets.S_ServerMessage;
import com.lineage.server.serverpackets.ServerBasePacket;
import com.lineage.server.templates.L1Castle;
import com.lineage.server.templates.L1Item;
import com.lineage.server.templates.L1ShopItem;
import com.lineage.server.utils.RangeInt;
import com.lineage.server.world.World;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class L1Shop {
  private final int _npcId;
  
  private final int _currencyItemId;
  
  private final List<L1ShopItem> _sellingItems;
  
  private final List<L1ShopItem> _purchasingItems;
  
  public L1Shop(int npcId, int currencyItemId, List<L1ShopItem> sellingItems, List<L1ShopItem> purchasingItems) {
    if (sellingItems == null || purchasingItems == null)
      throw new NullPointerException(); 
    this._npcId = npcId;
    this._currencyItemId = currencyItemId;
    this._sellingItems = sellingItems;
    this._purchasingItems = purchasingItems;
  }
  
  public int getNpcId() {
    return this._npcId;
  }
  
  public List<L1ShopItem> getSellingItems() {
    return this._sellingItems;
  }
  
  public List<L1ShopItem> getPurchasingItems() {
    return this._purchasingItems;
  }
  
  public boolean isSelling(int itemid) {
    Iterator<L1ShopItem> iterator = this._sellingItems.iterator();
    while (iterator.hasNext()) {
      L1ShopItem shopitem = iterator.next();
      if (shopitem.getItemId() == itemid)
        return true; 
    } 
    return false;
  }
  
  public boolean isPurchasing(int itemid) {
    Iterator<L1ShopItem> iterator = this._purchasingItems.iterator();
    while (iterator.hasNext()) {
      L1ShopItem shopitem = iterator.next();
      if (shopitem.getItemId() == itemid)
        return true; 
    } 
    return false;
  }
  
  private boolean isPurchaseableItem(L1ItemInstance item) {
    return (item != null && !item.isEquipped() && item.getEnchantLevel() == 0 && item.getBless() < 128);
  }
  
  private L1ShopItem getPurchasingItem(int itemId) {
    Iterator<L1ShopItem> iterator = this._purchasingItems.iterator();
    while (iterator.hasNext()) {
      L1ShopItem shopItem = iterator.next();
      if (shopItem.getItemId() == itemId)
        return shopItem; 
    } 
    return null;
  }
  
  public L1AssessedItem assessItem(L1ItemInstance item) {
    L1ShopItem shopItem = getPurchasingItem(item.getItemId());
    if (shopItem == null)
      return null; 
    return new L1AssessedItem(item.getId(), getAssessedPrice(shopItem), item.getName2());
  }
  
  private int getAssessedPrice(L1ShopItem item) {
    return (int)(item.getPrice() * ConfigRate.RATE_SHOP_PURCHASING_PRICE / item.getPackCount());
  }
  
  public List<L1AssessedItem> assessItems(L1PcInventory inv) {
    List<L1AssessedItem> result = new ArrayList<>();
    Iterator<L1ShopItem> iterator = this._purchasingItems.iterator();
    while (iterator.hasNext()) {
      L1ShopItem item = iterator.next();
      L1ItemInstance[] itemsId;
      int length = (itemsId = inv.findItemsId(item.getItemId())).length;
      int i = 0;
      while (i < length) {
        L1ItemInstance targetItem = itemsId[i];
        if (isPurchaseableItem(targetItem))
          result.add(
              new L1AssessedItem(targetItem.getId(), getAssessedPrice(item), targetItem.getName())); 
        i++;
      } 
    } 
    return result;
  }
  
  private boolean ensureSell(L1PcInstance pc, L1ShopBuyOrderList orderList) {
    int price = orderList.getTotalPrice();
    if (!RangeInt.includes(price, 0, 2000000000)) {
      pc.sendPackets((ServerBasePacket)new S_ServerMessage(904, "2000000000"));
      return false;
    } 
    Iterator<L1ShopBuyOrder> iterator = orderList.getList().iterator();
    while (iterator.hasNext()) {
      L1ShopBuyOrder order = iterator.next();
      int itemid = order.getItem().getItemId();
      if (itemid == 56148 && (
        pc.getInventory().findItemId(56147) != null || pc.getInventory().findItemId(56148) != null)) {
        pc.sendPackets((ServerBasePacket)new S_ServerMessage("身上已有妲蒂斯的魔力。"));
        return false;
      } 
      if (!pc.getInventory().checkItem(this._currencyItemId, price)) {
        L1Item item = ItemTable.get().getTemplate(this._currencyItemId);
        pc.sendPackets((ServerBasePacket)new S_ServerMessage(337, item.getName()));
        return false;
      } 
      int currentWeight = pc.getInventory().getWeight() * 1000;
      if ((currentWeight + orderList.getTotalWeight()) > pc.getMaxWeight() * 1000.0D) {
        pc.sendPackets((ServerBasePacket)new S_ServerMessage(82));
        return false;
      } 
      int DailyBuyingCount = order.getItem().getDailyBuyingCount();
      if (DailyBuyingCount <= 0)
        continue; 
      int AlreadyBoughtCount = pc.getQuest().get_step(itemid);
      int buyingcount = order.getCount();
      if (AlreadyBoughtCount >= DailyBuyingCount || buyingcount + AlreadyBoughtCount > DailyBuyingCount) {
        pc.sendPackets((ServerBasePacket)new S_ServerMessage("超过每日限制购买数量上限。"));
        return false;
      } 
      pc.getQuest().set_step(itemid, buyingcount + AlreadyBoughtCount);
    } 
    int totalCount = pc.getInventory().getSize();
    Iterator<L1ShopBuyOrder> iterator2 = orderList.getList().iterator();
    while (iterator2.hasNext()) {
      L1ShopBuyOrder order2 = iterator2.next();
      L1Item temp = order2.getItem().getItem();
      if (temp.isStackable()) {
        if (pc.getInventory().checkItem(temp.getItemId()))
          continue; 
        totalCount++;
        continue;
      } 
      totalCount++;
    } 
    if (totalCount > 180) {
      pc.sendPackets((ServerBasePacket)new S_ServerMessage(263));
      return false;
    } 
    return true;
  }
  
  private void payCastleTax(L1ShopBuyOrderList orderList) {
    L1TaxCalculator calc = orderList.getTaxCalculator();
    int price = orderList.getTotalPrice();
    int castleId = L1CastleLocation.getCastleIdByNpcid(this._npcId);
    int castleTax = calc.calcCastleTaxPrice(price);
    int nationalTax = calc.calcNationalTaxPrice(price);
    if (castleId == 7 || castleId == 8) {
      castleTax += nationalTax;
      nationalTax = 0;
    } 
    if (castleId != 0 && castleTax > 0) {
      L1Castle castle = CastleReading.get().getCastleTable(castleId);
      synchronized (castle) {
        long money = castle.getPublicMoney();
        money += castleTax;
        castle.setPublicMoney(money);
        CastleReading.get().updateCastle(castle);
      } 
      if (nationalTax > 0) {
        L1Castle aden = CastleReading.get().getCastleTable(7);
        synchronized (aden) {
          long money2 = aden.getPublicMoney();
          money2 += nationalTax;
          aden.setPublicMoney(money2);
          CastleReading.get().updateCastle(aden);
        } 
      } 
    } 
  }
  
  private void payDiadTax(L1ShopBuyOrderList orderList) {
    L1TaxCalculator calc = orderList.getTaxCalculator();
    int price = orderList.getTotalPrice();
    int diadTax = calc.calcDiadTaxPrice(price);
    if (diadTax <= 0)
      return; 
    L1Castle castle = CastleReading.get().getCastleTable(8);
    synchronized (castle) {
      long money = castle.getPublicMoney();
      money += diadTax;
      castle.setPublicMoney(money);
      CastleReading.get().updateCastle(castle);
    } 
  }
  
  private void payTownTax(L1ShopBuyOrderList orderList) {
    int price = orderList.getTotalPrice();
    if (!World.get().isProcessingContributionTotal()) {
      int town_id = L1TownLocation.getTownIdByNpcid(this._npcId);
      if (town_id >= 1 && town_id <= 10)
        TownReading.get().addSalesMoney(town_id, price); 
    } 
  }
  
  private void payTax(L1ShopBuyOrderList orderList) {
    payCastleTax(orderList);
    payTownTax(orderList);
    payDiadTax(orderList);
  }
  
  private void sellItems(L1PcInventory inv, L1ShopBuyOrderList orderList, L1PcInstance pc) {
    if (orderList == null)
      return; 
    int price = orderList.getTotalPrice();
    if (price <= 0)
      return; 
    if (!inv.consumeItem(this._currencyItemId, price))
      return; 
    Iterator<L1ShopBuyOrder> iterator = orderList.getList().iterator();
    while (iterator.hasNext()) {
      L1ShopBuyOrder order = iterator.next();
      int itemId = order.getItem().getItemId();
      long amount = order.getCount();
      int EnchantLevel = order.getItem().getEnchantLevel();
      L1ItemInstance item = ItemTable.get().createItem(itemId);
      if (amount <= 0L)
        continue; 
      item.setCount(amount);
      item.setEnchantLevel(EnchantLevel);
      item.setIdentified(true);
      inv.storeItem(item);
      pc.sendPackets((ServerBasePacket)new S_ServerMessage(403, item.getLogName()));
    } 
  }
  
  public void sellItems(L1PcInstance pc, L1ShopBuyOrderList orderList) {
    if (orderList.isEmpty())
      return; 
    if (!ensureSell(pc, orderList))
      return; 
    if (pc.getInventory().getSize() + orderList.getList().size() >= 180) {
      pc.sendPackets((ServerBasePacket)new S_ServerMessage(263));
      return;
    } 
    if (getNpcId() != 93214) {
      sellItems(pc.getInventory(), orderList, pc);
      return;
    } 
    if (!ensureCashSell2(pc, orderList, getNpcId()))
      return; 
    sellCashItems2(pc, pc.getInventory(), orderList, getNpcId());
  }
  
  private boolean ensureCashSell2(L1PcInstance pc, L1ShopBuyOrderList orderList, int npcId) {
    int price = orderList.getTotalPrice();
    L1Item item = ItemTable.get().getTemplate(95294);
    long srcCount = pc.getInventory().countItems(95294);
    long nc = price - srcCount;
    if (!pc.getInventory().checkItem(95294, price)) {
      pc.sendPackets((ServerBasePacket)new S_ServerMessage(337, String.valueOf(String.valueOf(item.getNameId())) + "(" + nc + ")"));
      return false;
    } 
    int currentWeight = pc.getInventory().getWeight() * 1000;
    if ((currentWeight + orderList.getTotalWeight()) > pc.getMaxWeight() * 1000.0D) {
      pc.sendPackets((ServerBasePacket)new S_ServerMessage(82));
      return false;
    } 
    int totalCount = pc.getInventory().getSize();
    Iterator<L1ShopBuyOrder> iterator = orderList.getList().iterator();
    while (iterator.hasNext()) {
      L1ShopBuyOrder order = iterator.next();
      L1Item temp = order.getItem().getItem();
      if (temp.isStackable()) {
        if (pc.getInventory().checkItem(temp.getItemId()))
          continue; 
        totalCount++;
        continue;
      } 
      totalCount++;
    } 
    if (totalCount > 180) {
      pc.sendPackets((ServerBasePacket)new S_ServerMessage(263));
      return false;
    } 
    if (price <= 0 || price > 100000000) {
      pc.sendPackets((ServerBasePacket)new S_Disconnect());
      return false;
    } 
    return true;
  }
  
  private void sellCashItems2(L1PcInstance pc, L1PcInventory inv, L1ShopBuyOrderList orderList, int npcId) {
    if (!inv.consumeItem(95294, orderList.getTotalPrice()))
      throw new IllegalStateException("尸魂币不足."); 
    L1ItemInstance item = null;
    Iterator<L1ShopBuyOrder> iterator = orderList.getList().iterator();
    while (iterator.hasNext()) {
      L1ShopBuyOrder order = iterator.next();
      int itemId = order.getItem().getItemId();
      int amount = order.getCount();
      int EnchantLevel = order.getItem().getEnchantLevel();
      item = ItemTable.get().createItem(itemId);
      if (amount <= 0)
        continue; 
      item.setCount(amount);
      item.setEnchantLevel(EnchantLevel);
      item.setIdentified(true);
      inv.storeItem(item);
      pc.sendPackets((ServerBasePacket)new S_ServerMessage(403, item.getLogName()));
    } 
  }
  
  public void buyItems(L1PcInstance pc, L1ShopSellOrderList orderList) {
    L1PcInventory inv = orderList.getPc().getInventory();
    int totalPrice = 0;
    for (L1ShopSellOrder order : orderList.getList()) {
      L1ItemInstance item = inv.getItem(order.getItem()
          .getTargetId());
      if (item == null)
        return; 
      if (item.isEquipped())
        return; 
      if (item.isSeal())
        return; 
      long count = inv.removeItem(order.getItem().getTargetId(), order.getCount());
      if (count > 0L) {
        totalPrice = (int)(totalPrice + order.getItem().getAssessedPrice() * count);
        sellnpcitem("IP(" + pc.getNetConnection().getIp() + ")" + "玩家" + ":【" + pc.getName() + "】将" + 
            order.getItem().getTargetName() + "(" + order.getCount() + ")个,卖给Npc获得金币(" + (
            order.getItem().getAssessedPrice() * count) + ")时间:" + "(" + 
            new Timestamp(System.currentTimeMillis()) + ")。");
        continue;
      } 
      sellnpcitem("IP(" + pc.getNetConnection().getIp() + ")" + "玩家非法贩售,数量小于0" + ":【" + pc.getName() + "】将" + 
          order.getItem().getTargetId() + "(" + order.getCount() + ")个,卖给Npc获得金币(" + (
          order.getItem().getAssessedPrice() * count) + ")时间:" + "(" + 
          new Timestamp(System.currentTimeMillis()) + ")。");
    } 
    totalPrice = RangeInt.ensure(totalPrice, 0, 2000000000);
    if (totalPrice > 0) {
      L1ItemInstance item = ItemTable.get().createItem(this._currencyItemId);
      item.setCount(totalPrice);
      pc.sendPackets((ServerBasePacket)new S_ServerMessage(403, item.getLogName()));
      inv.storeItem(item);
    } 
  }
  
  public L1ShopBuyOrderList newBuyOrderList() {
    return new L1ShopBuyOrderList(this);
  }
  
  public L1ShopSellOrderList newSellOrderList(L1PcInstance pc) {
    return new L1ShopSellOrderList(this, pc);
  }
  
  private static void sellnpcitem(String info) {
    try {
      BufferedWriter out = new BufferedWriter(new FileWriter("玩家纪录/万物回收商纪录.txt", true));
      out.write(String.valueOf(String.valueOf(info)) + "\r\n");
      out.close();
    } catch (IOException e) {
      e.printStackTrace();
    } 
  }
}
